package gee

import (
	"html/template"
	"log"
	"net/http"
	"strings"
)

type HandlerFunc func(*Context)

type Engine struct {
	*RouterGroup
	Router    *router
	groups    []*RouterGroup //store all groups
	templates *template.Template
	funcMap   template.FuncMap
}

func New() *Engine {
	engine := &Engine{
		Router: newRouter(),
	}
	engine.RouterGroup = &RouterGroup{engine: engine}
	engine.groups = []*RouterGroup{engine.RouterGroup}
	return engine
}

func Default() *Engine {
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

func (engine *Engine) AddRouter(method string, pattern string, handleFunc HandlerFunc) {
	engine.Router.addRouter(method, pattern, handleFunc)
}

func (engine *Engine) GET(pattern string, handleFunc HandlerFunc) {
	engine.AddRouter("GET", pattern, handleFunc)
}

func (engine *Engine) POST(pattern string, handleFunc HandlerFunc) {
	engine.AddRouter("POST", pattern, handleFunc)
}

func (engine *Engine) Run(addr string) {
	log.Println("access 127.0.0.1:", addr)
	log.Fatal(http.ListenAndServe(addr, engine))
}

func (engine *Engine) ServeHTTP(res http.ResponseWriter, req *http.Request) {
	var middileWares []HandlerFunc
	for _, group := range engine.groups {
		if strings.HasPrefix(req.URL.Path, group.prefix) {
			for _, middleware := range group.middileWares {
				middileWares = append(middileWares, middleware)
			}
		}
	}
	ctx := newContext(req, res)
	ctx.handlers = middileWares
	ctx.engine = engine
	engine.Router.handle(ctx)
}

// global handler function
func (engine *Engine) SetFuncMap(funcMap template.FuncMap) {
	engine.funcMap = funcMap
}

// global load template
func (engine *Engine) LoadHTMLGlob(patterns []string) {
	engine.templates = template.New("").Funcs(engine.funcMap)
	for _, pattern := range patterns {
		_, err := engine.templates.ParseGlob(pattern)
		if err != nil {
			log.Println(err.Error())
		}
	}
}
